﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using log4net;
using UpgradeFirwareAndThreadManagementLib;
using ConfigHelp;

namespace WatchdogSoftware
{
    public partial class FrmMain : Form
    {
        /// <summary>
        /// udp发送
        /// </summary>
        //UdpClient udp_send = new UdpClient(new IPEndPoint(IPAddress.Any, 0));
        /// <summary>
        /// udp接收，在这里相当于指定端口，即bind(65432)
        /// </summary>
        UdpClient udp_rec = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 65432));
        /// <summary>
        /// log日志
        /// </summary>
        ILog log = LogManager.GetLogger("WD");//这里算是一个用户标签
        /// <summary>
        /// 超时次数，5次重启
        /// 一次默认30秒，时间可改
        /// </summary>
        int timerout = 0;
        /// <summary>
        /// 超时最大次数
        /// </summary>
        int timerout_max = 5;
        /// <summary>
        /// 启动发送标志
        /// </summary>
        bool startSend = false;
        /// <summary>
        /// 重启等待时间，120秒
        /// </summary>
        int restartWaitTime = 120;
        /// <summary>
        /// 心跳间隔时间
        /// </summary>
        int HeartbeatTime = 30;
        /// <summary>
        /// 受控的软件名
        /// </summary>
        string softName = "Main.exe";
        /// <summary>
        /// 重启时间1
        /// </summary>
        DateTime restartTime1;
        /// <summary>
        /// 重启时间2
        /// </summary>
        DateTime restartTime2;
        /// <summary>
        /// 接收线程
        /// </summary>
        Thread recThread = null;
        /// <summary>
        /// 发送线程
        /// </summary>
        Thread sendThread = null;
        /// <summary>
        /// 退出标志
        /// </summary>
        bool exitFlag = false;
        
        public FrmMain()
        {
            log.Info("system start");
            InitializeComponent();
            this.ShowInTaskbar = false;//不显示在系统任务栏
            notifyIcon.Visible = true;
            timer1.Enabled = false;
            //启动线程
            StartThread();
            //读取配置参数
            ReadCfgParam();

            StartSoft();
        }

        /// <summary>
        /// 启动线程
        /// </summary>
        private void StartThread()
        {
            recThread = new Thread(UdpReceive);
            recThread.IsBackground = true;
            recThread.Start();

            sendThread = new Thread(UdpSend);
            sendThread.IsBackground = true;
            sendThread.Start();
        }

        /// <summary>
        /// 读取配置参数
        /// </summary>
        private void ReadCfgParam()
        {
            //读超时等待参数
            try
            {
                restartWaitTime = Convert.ToInt32(ConfigHelper.GetAppConfig("RestartWaitTime"));
            }
            catch { log.Warn("RestartWaitTime读取失败，使用默认值，120秒"); }

            //读超时等待参数
            try
            {
                timerout_max = Convert.ToInt32(ConfigHelper.GetAppConfig("TimeroutMax"));
            }
            catch { log.Warn("TimeroutMax，使用默认值，5次"); }

            //读取受控软件名
            try
            {
                softName = ConfigHelper.GetAppConfig("SoftName");
            }
            catch { log.Warn("SoftName读取失败，将使用默认的软件名Main.exe"); }

            //读取心跳时间间隔
            try
            {
                HeartbeatTime = Convert.ToInt32(ConfigHelper.GetAppConfig("HeartbeatTime"));
            }
            catch { log.Warn("HeartbeatTime，使用默认值，30秒"); }

            //读取重启时间1
            try
            {
                restartTime1 = Convert.ToDateTime(ConfigHelper.GetAppConfig("RestartTime1"));
            }
            catch {
                restartTime1 = Convert.ToDateTime("06:00:00");
                log.Warn("RestartTime1，使用默认值，06:00:00");
            }

            //读取重启时间2
            try
            {
                restartTime2 = Convert.ToDateTime(ConfigHelper.GetAppConfig("RestartTime2"));
            }
            catch
            {
                restartTime2 = Convert.ToDateTime("10:30:00");
                log.Warn("RestartTime2，使用默认值，10:30:00");
            }
        }

        /// <summary>
        /// udp接收线程
        /// </summary>
        private void UdpReceive()
        {
            //IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 65432);
            IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 65432);
            log.Info("udp receive thread start");
            string[] strCmd = { "Heartbeat", "Heartbeat_ACK","Restart" };

            while (true)
            {
                try {
                    byte[] recData = udp_rec.Receive(ref endpoint);
                    string cmd = CMyConvert.AsciiByteToString(recData);
                    log.Debug("收到的命令为:" + cmd);
                    switch (cmd)
                    {
                        //受监听软件启动结束时，发此指令上来然后来软件再开始发送心跳包
                        //如果对方没有收到心跳包，即每隔3秒发送一次
                        case "StartEnd": {
                                startSend = true;
                                
                                this.Invoke(new EventHandler(delegate
                                {
                                    timer1.Enabled = false;
                                }));
                            } break;
                        case "Heartbeat_ACK": {
                                timerout = 0;
                            } break;
                        case "Soft_Exit_OK": {
                                startSend = false;//对方正在退出
                                timerout = 0;
                                log.Info("受控软件正在关闭");
                                Thread.Sleep(1000 * restartWaitTime);//120秒后重启

                                this.Invoke(new EventHandler(delegate
                                {
                                    timer1.Interval = 100;
                                    timer1.Enabled = true;
                                }));
                            }
                            break;
                    }
                } catch(Exception ex) {
                    log.Error(ex.Message);
                }
            }
        }

        /// <summary>
        /// 重动软件
        /// </summary>
        private void StartSoft()
        {
            log.Info("向系统发送启动软件指令");
            startSend = false;
            System.Diagnostics.Process.Start(@"" + softName);
            timerout = 0;
        }

        /// <summary>
        /// udp发送
        /// </summary>
        private void UdpSend()
        {
            log.Info("udp send thread start");
            while (startSend == false) Thread.Sleep(50);
            //对方的节点
            IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 65433);
            
            while (true)
            {
                try {
                    string cmd = "";
                    TimeSpan ts1 = restartTime1 - DateTime.Now;
                    TimeSpan ts2 = restartTime2 - DateTime.Now;

                    if ((Math.Abs(ts1.TotalSeconds) < HeartbeatTime) || (Math.Abs(ts2.TotalSeconds) < HeartbeatTime))
                    {
                        cmd = "Soft_Exit";//定时重启才发此指令
                        log.Info("发送重启指令");
                    }
                    else
                    {
                        timerout++;
                        if (timerout > timerout_max)//超时
                        {
                            log.Warn("timerout = " + timerout.ToString() + "次");
                            //StartSoft();
                            this.Invoke(new EventHandler(delegate
                            {
                                timer1.Interval = 100;
                                timer1.Enabled = true;
                            }));
                            
                            goto goto_label;
                        }
                        else
                        {
                            log.Debug("发送心跳");
                            cmd = "Heartbeat";
                        }
                    }

                    byte[] barr = CMyConvert.StringToAsciiByte(cmd);
                    udp_rec.Send(barr, barr.Length, ipe);
goto_label:
                    Thread.Sleep(1000 * HeartbeatTime);
                    while (startSend == false) Thread.Sleep(500);

                } catch(Exception ex) {
                    log.Error("UdpSend" + ex.Message);
                }
            }
        }

        private void ShowDisplay_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Normal;
        }

        private void ExitApp_Click(object sender, EventArgs e)
        {
            exitFlag = true;
            Application.Exit();
        }

        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (exitFlag == false)
                e.Cancel = true;
            this.WindowState = FormWindowState.Minimized;
        }

        private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            //双击还原
            ShowDisplay.PerformClick();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            //重启软件
            StartSoft();

            if(timer1.Interval != 30000)
            {
                timer1.Enabled = false;
                timer1.Interval = 30000;
                timer1.Enabled = true;
            }
        }
    }
}
